package com.chenjiaru.thread.lock;

import com.chenjiaru.thread.util.ThreadUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/*
 * ReadWriteLock:读写锁
 * 写写，写读，读写 互斥
 * 读读不互斥
 */
@Slf4j
public class ReadWriteLockDemo {

    private static Integer num = 0;


    public static void main(String[] arr) {
        ReadWriteLockDemo readWriteLockDemo = new ReadWriteLockDemo();
        readWriteLockDemo.writeAndWrite();

    }

    /**
     * 读锁和读锁（不互斥）
     */
    public void readAndRead() {
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        new Thread(() -> {
            try {
                readWriteLock.readLock().lock();
                ThreadUtil.mySleep(2000);
                log.info("readLock1:num={}", num);
            } finally {
                readWriteLock.readLock().unlock();
            }
        }).start();

        ThreadUtil.mySleep(200);
        new Thread(() -> {
            try {
                readWriteLock.readLock().lock();
                log.info("readLock2:num={}", num);
            } finally {
                readWriteLock.readLock().unlock();
            }
        }).start();
    }

    /**
     * 读锁和写锁（互斥）
     */
    public void readAndWrite() {
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        new Thread(() -> {
            try {
                readWriteLock.readLock().lock();
                log.info("readLock:num={}", num);
                ThreadUtil.mySleep(2000);
            } finally {
                readWriteLock.readLock().unlock();
                log.info("释放锁...");
            }
        }).start();

        ThreadUtil.mySleep(200);
        new Thread(() -> {
            try {
                readWriteLock.writeLock().lock();
                log.info("writeLock:num={}", ++num);
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();
    }

    /**
     * 写锁和读锁（互斥）
     */
    public void writeAndRead() {
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        new Thread(() -> {
            try {
                readWriteLock.writeLock().lock();
                log.info("writeLock:num={}", ++num);
                ThreadUtil.mySleep(2000);
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();

        ThreadUtil.mySleep(200);
        new Thread(() -> {
            try {
                readWriteLock.readLock().lock();
                log.info("readLock:num={}", num);
            } finally {
                readWriteLock.readLock().unlock();
            }
        }).start();
    }

    /**
     * 写锁和写锁（互斥）
     */
    public void writeAndWrite() {
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        new Thread(() -> {
            try {
                readWriteLock.writeLock().lock();
                ThreadUtil.mySleep(2000);
                log.info("writeLock1:num={}", ++num);
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();

        ThreadUtil.mySleep(200);
        new Thread(() -> {
            try {
                readWriteLock.writeLock().lock();
                log.info("writeLock2:num={}", ++num);
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();
    }


}




